// 根据jsx array创建对象
function buildObjectFromArray(parent, options) {

    var object = options[0];
    var Class = typeof object === 'string' ? classTypes[object] || Node : object;

    object = new Class();

    if (object.$checkParent)
    {
        object.$checkParent(parent);
    }

    object.parent = parent;
    object.__load(options);

    return object;
}


function buildObjectChildren(object, options) {

    var build = buildObjectFromArray;
    var children = object.__children;
    var length;

    if (typeof options === 'object' && (length = options.length))
    {
        children.length = length;

        for (var i = 0; i < length; i++)
        {
            children[i] = build(object, options[i]);
        }
    }
    else
    {
        children[0] = build(object, ['span', null, options]);
    }
}



// 节点基类
function Node() {

    this.init();
}


yaxi.Node = Object.extend(function (base) {



    // 缓存数组(复用以提升性能)
    function CacheArray() {

        var index = 0;
        var cache = { length: 0, push: push };
        var init = CacheArray.init || (CacheArray.init = new Array(1 << 16));

        function push(item) {

            cache[index++] = item;
        }

        // 初始化缓存
        init.push.apply(cache, init);

        // 重载length属性
        $define(cache, 'length', {

            get: function () {

                return index;
            },
            set: function (value) {

                index = (value |= 0) >= 0 ? value : 0;
            }
        });

        return cache;
    }



    // 加载时查找可视节点集合缓存池
    var loadFindCachePool = [];

    // 变化的节点集合缓存(复用数组提升性能)
    var updatingNodes = new Array(1 << 16);

    // 变化的节点集合缓存索引
    var updatingIndex = 0;

    // 更新时查找可视节点集合缓存(复用数组提升性能)
    var updateFindCache = new CacheArray();

    // 子项onload缓存
    var onloadNodeCache = new CacheArray();




    // 是否虚拟节点
    this.__virtual = false;



    // 子项集合
    $define(this, 'children', {

        get: function () {

            return this.__children;
        }
    });



    // 节点自定制绑定函数
    function nodeBindingFn() {

        var target = this.target;
        var name = this.property;
        var value = this.fn(target);
        var dom = target.dom;

        switch (name)
        {
            case 'class':
                dom.className = value;
                break;

            case 'style':
                loadNodeStyle(dom.style, value);
                break;

            case 'text':
                dom.textContent = value;
                break;

            default:
                if (value !== false)
                {
                    dom.setAttribute(name, value !== true ? value : name);
                }
                else
                {
                    dom.removeAttribute(name);
                }
                break;
        }
    }


    // 加载节点样式
    function loadNodeStyle(style, values) {

        for (var name in values)
        {
            style[name] = values[name];
        }
    }


    // 查找可视对象集
    function findVisualObjects(node, outputs) {

        var destroyObjectFn = destroyObject;
        var children = node.__children;
        var index = 0;

        while (node = children[index++])
        {
            if (node.__virtual)
            {
                node.getVisualObjects(outputs, destroyObjectFn);
            }
            else
            {
                outputs.push(node);
            }
        }

        return outputs;
    }


    // 异步更新全部标记过的节点
    function update() {

        var updatings = updatingNodes;
        var cache = updateFindCache;
        var node;

        // 每次动态检测updatingIndex解决在update时有新的节点需要更新的问题
        for (var i = 0; i < updatingIndex; i++)
        {
            if (node = updatings[i])
            {
                // 重置缓存索引
                cache.length = 0;

                findVisualObjects(node, cache);
                updateNode(node.dom, cache);

                node.__updating = 0;
                updatings[i] = null;
            }
        }

        // 最后重置缓存索引
        updatingIndex = 0;
    }


    // 更新单个节点
    function updateNode(domParent, childNodes) {

        var last = childNodes.length;
        var node, domRef, dom;

        if (last > 0)
        {
            domRef = domParent.firstChild;

            for (var i = 0; i < last; i++)
            {
                node = childNodes[i];
                childNodes[i] = null;

                if (dom = node.dom)
                {
                    // 子控件没有渲染过则先渲染
                    if (node.__children[0] && !dom.firstChild)
                    {
                        node.renderChildren();
                    }

                    if (dom === domRef)
                    {
                        domRef = domRef.nextSibling;
                    }
                    else if (domRef)
                    {
                        domParent.replaceChild(dom, domRef);
                        domRef = dom.nextSibling;
                    }
                    else
                    {
                        domParent.appendChild(dom);
                    }
                }
            }
        }
        else
        {
            domParent.textContent = '';
        }
    }


    // 销毁对象
    function destroyObject(object) {

        var dom, parentNode;

        if (object.__virtual) // 虚拟节点
        {
            destroyVirtualObject(object);
        }
        else if ((dom = object.dom) && (parentNode = dom.parentNode))
        {
            // 移除节点
            parentNode.removeChild(dom);
        }

        // 销毁
        object.destroy();
    }


    // 销毁虚拟对象
    function destroyVirtualObject(virtual) {

        var children = virtual.__children;
        var object, dom;

        for (var i = children.length; i--;)
        {
            if (object = children[i])
            {
                if (object.__virtual)
                {
                    destroyVirtualObject(object);
                }
                else if ((dom = object.dom) && (object = dom.parentNode))
                {
                    // 移除节点
                    object.removeChild(dom);
                }
            }
        }
    }



    // 初始化节点(new时自动调用)
    this.init = function () {

        // 关联的dom对象
        this.dom = null;

        // 父节点
        this.parent = null;

        // 子项集合
        this.__children = [];

        // 绑定
        this.__bindings = null;

        // 标记是否需要更新子项
        this.__updating = 0;
    }



    // 加载钩子
    this.onload = null;


    /**
     * 从json结构加载组件(jsx会自动编译成此结构)
     * 
     * @param {Array} options eg:
     * [
     *   'view',
     *   null,
     *   [
     *       ['span', null, 'test1'],
     *       ['span', null, 'test2'],
     *   ]
     * ]
    */
    this.load = function (options) {

        this.__load(options || []);

        if (this.__children[0])
        {
            this.renderChildren();
        }
        else if (this.onload)
        {
            this.onload();
        }
    }


    // 渲染节点
    this.renderNode = function (tagName, properties) {

        var dom = this.dom || (this.dom = document.createElement(tagName || 'div'));

        for (var name in properties)
        {
            var value = properties[name];

            switch (name)
            {
                case 'class':
                    dom.className = value;
                    break;

                case 'style':
                    loadNodeStyle(dom.style, value);
                    break;

                case 'text':
                    dom.textContent = value;
                    break;

                case 'bindings':
                    for (var key in value)
                    {
                        bindProperty(this, key, value[key], nodeBindingFn);
                    }
                    break;

                case 'events':
                    for (var key in value)
                    {
                        dom.addEventListener(key, value[key]);
                    }
                    break;

                case 'ref':
                    value(this);
                    break;

                default:
                    if (value !== false)
                    {
                        dom.setAttribute(name, value !== true ? value : name);
                    }
                    break;
            }
        }
    }


    // 渲染子节点
    this.renderChildren = function (onload) {

        var onloadCache = onloadNodeCache;
        var findCache, fragment, node;

        if (findCache = loadFindCachePool.pop())
        {
            fragment = findCache.fragment;
        }
        else
        {
            findCache = new CacheArray();
            findCache.fragment = fragment = document.createDocumentFragment();
        }

        // 递归查找可视节点
        findVisualObjects(this, findCache);

        // 添加子节点到文档碎片
        for (var i = 0, l = findCache.length; i < l; i++)
        {
            node = findCache[i];

            // 有子项继续递归渲染
            if (node.__children[0])
            {
                node.renderChildren(false);
            }
            else if (node.onload) // 否则添加onload
            {
                onloadCache.push(node);
            }

            fragment.appendChild(node.dom);
            findCache[i] = null;
        }

        // 退回缓存池以备复用
        findCache.length = 0;
        loadFindCachePool.push(findCache);

        // 添加文档碎片到dom树
        this.dom.appendChild(fragment);

        // 记录onload
        if (this.onload)
        {
            onloadCache.push(this);
        }

        // onload处理
        if (onload !== false)
        {
            // 先执行子项的onload
            for (var i = 0, l = onloadCache.length; i < l; i++)
            {
                onloadCache[i].onload();
            }

            // 重置onload缓存
            onloadCache.length = 0;
        }
    }


    // 加载组件内部方法
    this.__load = function (options) {

        this.renderNode(options[0], options[1]);

        if (options[2] !== void 0)
        {
            // 有子项时需等子项渲染完毕后才执行onload钩子
            if (typeof options[2] === 'object')
            {
                buildObjectChildren(this, options[2]);
                return;
            }

            this.dom.textContent = options[2];
        }

        if (this.onload)
        {
            this.onload();
        }
    }



    // 标记节点无效(需要更新子节点)
    this.invalidate = function () {

        if (!this.__updating)
        {
            var index = updatingIndex++;

            this.__updating = 1;

            updatingNodes[index] = this;

            if (!index)
            {
                microtask(update);
            }
        }
    }



    // 销毁钩子
    this.ondestroy = null;



    // 销毁
    this.destroy = function () {

        var children = this.__children;
        var any;

        if (this.ondestroy)
        {
            this.ondestroy();
        }

        for (var i = children.length; i--;)
        {
            children[i].destroy();
        }

        if (any = this.__bindings)
        {
            unbindProperty(any);
            this.__bindings = null;
        }

        this.parent = this.dom = null;
    }



}, Node);
